#include <iostream>
#include <string>
#include <initializer_list>
#include <vector>
//#include <error.h>

#include "chapter_6.h"

using std::vector;
using std::string;
using std::cout;
using std::endl;
using std::cin;

#define NDEBUG  // 不执行调试代码

int  count_calls()
{

	// 局部静态变量只在第一次调用时初始化，并存在于函数运行的整个周期
	static int ctr = 0;
	return ++ ctr;
}

int testLocalObject()
{

	for (int i = 0; i < 10; ++i)
		cout << count_calls() << endl;
	return 0;
}

string::size_type referReturn(const string& s, char c, string::size_type &occurs)
{

	auto ret = s.size();
	occurs = 0;

	for (decltype(ret) i = 0; i != s.size(); ++i)
	{
		if (c == s[i])
		{
			if (s.size() == ret)
				ret = i;
			++occurs;
		}
	}
	return ret;
}

int t6_10(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
	return 0;
}

int t6_12(int &a, int &b)
{

	int temp = a;
	a = b;
	b = temp;
	return 0;
}


int fcn(int i)
{
	i *= 2;
	return i;
}

bool is_empty(const string &s)
{
	return s.empty();
}

bool hasUpper(const string &s)
{
	for (auto c: s)
	{
		if (isupper(c))
			return true;
	}

	return false;
}

void stol(string &s)
{
	for (auto &c: s)
	{
		if (isupper(c))
			c = tolower(c);
	}

	return;
}

void print(const int *beg, const int *end)
{
	while (beg != end)
		cout << *beg++ << " ";
	cout << endl;
}

void print_v2(int (&arr)[10])
{
	for (auto i: arr)
	{
		cout << i << " ";
	}
	cout << endl;
}

void print_v3(int (*matrix)[4], int rowSize)
{
	for (int i = 0; i != rowSize; ++i)
	{
		for (auto i: *(matrix + i))
		{
			cout << i << " ";
		}
		cout << endl;
	}
}

void print_v4(int matrix[][4], int rowSize)
{
	for (int i = 0; i != rowSize; ++i)
	{
		for (auto i: *(matrix + i))
		{
			cout << i << " ";
		}
		cout << endl;
	}
}

void error_msg(std::initializer_list<string> il)
{
//	cout << e.message() << ": ";
	for (const auto &elem: il)
		cout << elem << " ";
	cout << endl;
}

int printVector(vector<int>::const_iterator beg, vector<int>::const_iterator end)
{
	// end指向尾后
	if (beg != end)
	{
		cout << *beg++ << "";
		printVector(beg, end);
	}
}

int t6_33()
{
	vector<int> v{0, 1, 2, 3, 4, 5, 5, 6, 7};
	printVector(v.begin(), v.end());
	return 0;
}

int factorial(int val)
{
	if (val > 1)
		return factorial(val - 1) * val;
}

int t6_35()
{
	int n = 4;
	cout << factorial(n) << endl;
	return 0;
}

//string  (&getString(const char &c))[10];

using type_name  = vector<string,std::allocator<string> >;
type_name getString(const char &c)
{
	vector<string> vs;
	for (int i = 0; i < 10; ++i)
	{
		string tstr;
		for (int j = 0; j < i + 1; ++j)
		{
			tstr += c;
		}
		vs.push_back(tstr);
	}
	return vs;
}

//using strArr = string (&arrRef)[10];
//typedef string strArr[10];
int (*testArr(int result[10][10]))[10]
{
	// 注意这里的这个定义方法
	for (int i = 0; i < 10; ++i)
	{
		for (int j = 10 - 1; j >= 0; --j)
		{
			result[i][j] = i * j;
			cout << result[i][j] << " ";
		}
		cout << endl;
	}
	return result;
}

string (&testSrr(string (&result)[10]))[10]
{
	// 注意这里的这个定义方法
	// 注意这里数组引用和引用数组的区别
	string tstr;
	for (int i = 0; i < 10; ++i)
	{
		tstr = "";
		for (int j = 1; j < i + 1; ++j)
		{
			tstr += "q";
		}
		result[i] = tstr;
	}
	return result;
}

// 测试函数重载的规则
int print(int *a, int *b)
{
	cout << "a * b = " << *a * *b << endl;
	return 0;
}

void print(int i)
{
	cout << "i: " << i << endl;
}

void print(int i);

bool isShorter(const string &s1, const string &s2)
{
	return (s1.size() < s2.size());
}

void print_vec(vector<int>& ivec)
{
	#ifndef NDEBUG
		cout << "vector's size is " << ivec.size() << endl;
	#endif // NDEBUG

    if (!ivec.empty()) {
        auto tmp = ivec.back();  // 返回最后一个元素的引用
        ivec.pop_back();
        print_vec(ivec);
        cout << tmp << " ";
    }
//    cout << endl;
}

int t6_47()
{
	vector<int> v{0,1,2,3,3,4,4,5,5};
	print_vec(v);
	return 0;
}

bool isEqul(const string &s1, const string &s2)
{
	return s1 == s2;
}

void f(int i)
{
	cout << "int i = " << i << endl;
}

void f()
{
	cout << "void f()" << endl;
}

void f(int a, int b)
{
	cout << "int a + b = " << a + b << endl;
}

void f(double a, double b=3.14)
{
	cout << "double a + b = " << a + b << endl;
}

bool (*pf)(const string &s1, const string &s2) = isEqul;

bool isEqul2(bool (*pf)(const string &s1, const string &s2), const string &s1, const string &s2)
{
	return pf(s1, s2);
}

int sum(int a, int b)
{
	return a + b;
}

int (*pp)(int a, int b) = sum;

int t6_54()
{
	vector<int (*)(int, int)> v;
	v.push_back(pp);

	cout << "1 + 2 = " << v[0](1, 2) << endl;
	return 0;
}

int main06()
{
//	testLocalObject();

	string::size_type size = 0;
	string::size_type ret = referReturn("abcdagdhaqqgwqeqrrwq", 'q', size);
	cout << "ret: " << ret << endl << "occurs: " << size << endl
			<< "------------------------------" << endl;

	int a{1}, b{2};
	t6_10(&a ,&b);
	cout << "a: " << a << " " << "b: " << b << endl
			<< "----------------------------" << endl;

	t6_12(a, b);
	cout << "a: " << a << " " << "b: " << b << endl
				<< "----------------------------" << endl;

	const int i = 1;  // 形参自动忽略顶层const
	cout << "i* 2 = " << fcn(i) << endl
			<< "---------------------------------";

	string s = "hadjhadjkadQLQkjaf";  // is_empty()函数应该设置为const
	cout << " is s empty? " <<  is_empty(s) << endl;

	cout << "has upper? " << hasUpper(s) << endl;

	stol(s);
	cout << "to lower: " << s << endl
			<< "----------------------------------" << endl;

	int j[10] = {1,2,3,4,5,6,7,8,9,0};
	print(std::begin(j), std::end(j));
	cout << "-------------------------------------" << endl;
	int k[11] = {0};
	print_v2(j);
	cout << "-------------------------------------" << endl;
	int l[3][4]{0,1,2,3,4,5,6,7,0,9,8,7};
	print_v3(l, 3);
	cout << "-------------------------------------" << endl;
	print_v4(l, 3);
	cout << "-------------------------------------" << endl;
	error_msg({"hello", "world"});
	cout << "-------------------------------------" << endl;
	t6_33();
	cout << "\n-------------------------------------" << endl;
	t6_35();
	cout << "-------------------------------------" << endl;

	vector<string> vs = getString('c');

	for (int i = 0; i < 10; ++i)
	{
		cout << vs[i] << endl;
	}

	cout << "--------------------------------------" << endl;

	string srr[10];
	for (int i = 0; i < 10; ++i)
	{
		string tstr;
		for (int j = 0; j < i + 1; ++j)
			tstr += "z";
		srr[i] = tstr;
	}

	for (auto s: srr)
	{
		cout << s << endl;
	}

	cout << "------------数组指针的引用-------------" << endl;

	// 这里返回数组的指针的引用
	int result[10][10];
	int (*srr_3)[10] = testArr(result);
	cout << endl << "srr_3[0][9]: " << int(srr_3[2][9]) << endl;

	string result_s[10];
	string (&srr_4)[10] = testSrr(result_s);
	for (auto s: srr_4)
	{
		cout << s << endl;
	}
	cout << "-----------函数重载--------------" << endl;
	int a_1{ 0 }, b_1{ 0 };
	const int *p = &a_1, *q = &b_1;
	print(p, q);

	/*
	 * 函数重载与作用域
	 * 将函数声明置于局部作用域内不是一个明智的选择
	 */

	void print(int i);
//	print(p, q);  // 会覆盖全局的声明

	cout << "----------函数相关的特殊语言特性----------------";
	/*
	 * 1. 默认实参
	 * 2. 内联函数
	 * 3. 常量表达式constexpr函数
	 */

	string s1{"hello"}, s2{" world!"};
	cout << endl << (isShorter(s1, s2) ? "s1 < s2" : "s1 > s2");  // 注意这里运算符的先后顺序
	cout << endl;

	cout << "----------------调试助手---------------------" << endl;
	t6_47();
	cout << endl;

	cout << "-----------------函数匹配---------------------" << endl;
	void f(int);
	void f(int, int);
	void f(double, double=3.14);
	f(5);
//	f(42, 5.4);  // 这里就具有二义性了
	cout << endl;
	cout << "----------------函数指针--------------------" << endl;
	s1 = "nihao", s2 = "nihao";
	cout << "test fun pointer: " << (isEqul2(pf, s1, s2) ? "相等" : "不相等") << endl;

	t6_54();

	return 0;
}

int main06_1(int argc, char*argv[])
{
	if (3 != argc)
	{
		std::cerr << "Usage: should have two argument!";
		return -1;
	}

	string s = string(argv[1]) + string(argv[2]);
	cout << s << endl;
	return 0;
}
